﻿\myparagraph{ARM64}

\mysubparagraph{\Optimizing GCC (Linaro) 4.9}

\lstinputlisting[style=customasmARM]{patterns/10_strings/1_strlen/ARM/ARM64_GCC_O3_RU.lst}

Алгоритм такой же как и в \myref{strlen_MSVC_Ox}: 
найти нулевой байт, затем вычислить разницу между указателями, затем отнять 1 от результата.
Комментарии добавлены автором книги.

Стоит добавить, что наш пример имеет ошибку: \TT{my\_strlen()}
возвращает 32-битный \Tint, тогда как должна возвращать \TT{size\_t} или иной 64-битный тип.

Причина в том, что теоретически, \TT{strlen()} можно вызывать для огромных блоков в памяти,
превышающих 4GB, так что она должна иметь возможность вернуть 64-битное значение на 64-битной платформе.

Так что из-за моей ошибки, последняя инструкция \SUB работает над 32-битной частью регистра, тогда
как предпоследняя \SUB работает с полными 64-битными частями (она вычисляет разницу между указателями).

Это моя ошибка, но лучше оставить это как есть, как пример кода, который возможен в таком случае.

\mysubparagraph{\NonOptimizing GCC (Linaro) 4.9}

\lstinputlisting[style=customasmARM]{patterns/10_strings/1_strlen/ARM/ARM64_GCC_O0_RU.lst}

Более многословно.
Переменные часто сохраняются в память и загружаются назад (локальный стек).
Здесь та же ошибка: операция декремента происходит над 32-битной частью регистра.

